﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using Vidyano.Components.Authenticator;

namespace RapidDownloader.Model
{
    public sealed class RapidShareAuthenticatorService : AuthenticatorService
    {
        #region Fields

        private Dictionary<string, string> accountDetails;
        private IDisposable accountPolling;

        private static readonly string settingsFolder;
        private static readonly string settingsFile;

        #endregion

        #region Constructors

        static RapidShareAuthenticatorService()
        {
            settingsFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "RapidDownloader");
            settingsFile = Path.Combine(settingsFolder, "Settings.dat");
        }

        public RapidShareAuthenticatorService()
        {
            AddUserNamePasswordParameters();

            try
            {
                if (File.Exists(settingsFile))
                {
                    var protectedData = File.ReadAllBytes(settingsFile);
                    var unprotectedData = ProtectedData.Unprotect(protectedData, new byte[0], DataProtectionScope.CurrentUser);
                    var loginData = Encoding.ASCII.GetString(unprotectedData).Split('\n');

                    this["UserName"].DefaultValue = loginData[0];
                    this["Password"].DefaultValue = loginData[1];
                }
            }
            catch { }
        }

        #endregion

        #region Properties

        public override bool TryAutomatedAuthenticate
        {
            get
            {
                return this["UserName"].Value != null;
            }
        }

        public int Rapids
        {
            get
            {
                string rapids;
                return accountDetails != null && accountDetails.TryGetValue("rapids", out rapids) ? Convert.ToInt32(rapids) : -1;
            }
        }

        public string ValidUntil
        {
            get
            {
                string validUntil;
                return accountDetails != null && accountDetails.TryGetValue("billeduntil", out validUntil) ? new DateTime(1970, 1, 1).AddSeconds(Convert.ToInt32(validUntil)).ToLongDateString() : "Unknown";
            }
        }

        #endregion

        #region Public Methods

        public override void Authenticate()
        {
            IsAuthenticated = PopulateAccountDetails();

            if (IsAuthenticated)
            {
                try
                {
                    var loginData = string.Format("{0}\n{1}", this["UserName"].Value, this["Password"].Value);
                    var unprotectedData = Encoding.ASCII.GetBytes(loginData);
                    var protectedData = ProtectedData.Protect(unprotectedData, new byte[0], DataProtectionScope.CurrentUser);

                    Directory.CreateDirectory(settingsFolder);
                    File.WriteAllBytes(settingsFile, protectedData);
                }
                catch { }

                if (accountPolling != null)
                    accountPolling.Dispose();

                accountPolling = Observable.Interval(TimeSpan.FromMinutes(1)).Subscribe(n =>
                    {
                        try
                        {
                            PopulateAccountDetails();
                        }
                        catch (WebException) { }
                    });
            }
        }

        #endregion

        #region Private Methods

        private bool PopulateAccountDetails()
        {
            var loginResponse = WebHelper.DownloadString(string.Format("http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=getaccountdetails_v1&type=prem&login={0}&password={1}", this["UserName"].Value, this["Password"].Value));

            if (!loginResponse.StartsWith("ERROR"))
            {
                accountDetails = loginResponse.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries).Select(entry => entry.Split('=')).ToDictionary(entry => entry[0].Trim(), entry => entry[1].Trim());
                SendPropertyChanged(string.Empty);

                return true;
            }

            return false;
        }

        #endregion
    }
}